package com.topica.adapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import com.topica.R;

public class SlideImageAdapter extends BaseAdapter {

	private LayoutInflater mInflater;
	private static final String[] paths = { "/mnt/sdcard/image1.jpg",
			"/mnt/sdcard/image2.jpg", "/mnt/sdcard/image3.jpg",
			"/mnt/sdcard/image4.jpg", "/mnt/sdcard/image5.jpg",
			"/mnt/sdcard/image6.jpg" };
	private int reqWidth;
	private int reqHeight;
	private static final String TAG = "Touch";
    @SuppressWarnings("unused")
    private static final float MIN_ZOOM = 1f,MAX_ZOOM = 4f;

    // These matrices will be used to scale points of the image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();

    // The 3 states (events) which the user is trying to perform
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    // these PointF objects are used to record the point(s) the user is touching
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;


	public SlideImageAdapter(Context context) {
		mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		DisplayMetrics metrics = context.getResources().getDisplayMetrics();
		reqHeight = metrics.heightPixels;
		reqWidth = metrics.widthPixels;
	}

	@Override
	public int getCount() {
		return paths.length;
	}

	@Override
	public Object getItem(int position) {
		return position;
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (convertView == null) {
			convertView = mInflater.inflate(R.layout.image_item, null);
		}
		ImageView image = (ImageView) convertView.findViewById(R.id.slide_image);
		Bitmap original = decodeSampledBitmap(paths[position], 400, 500);
		Bitmap actual = Bitmap.createScaledBitmap(original, reqWidth, reqHeight, true);
		original.recycle();
		original = null;
		image.setImageBitmap(actual);
		image.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				ImageView view = (ImageView) v;
		        view.setScaleType(ImageView.ScaleType.MATRIX);
		        float scale;

		        dumpEvent(event);
		        // Handle touch events here...

		        switch (event.getAction() & MotionEvent.ACTION_MASK) 
		        {
		            case MotionEvent.ACTION_DOWN:   // first finger down only
		                                                savedMatrix.set(matrix);
		                                                start.set(event.getX(), event.getY());
		                                                Log.d(TAG, "mode=DRAG"); // write to LogCat
		                                                mode = DRAG;
		                                                break;

		            case MotionEvent.ACTION_UP: // first finger lifted

		            case MotionEvent.ACTION_POINTER_UP: // second finger lifted

		                                                mode = NONE;
		                                                Log.d(TAG, "mode=NONE");
		                                                break;

		            case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down

		                                                oldDist = spacing(event);
		                                                Log.d(TAG, "oldDist=" + oldDist);
		                                                if (oldDist > 5f) {
		                                                    savedMatrix.set(matrix);
		                                                    midPoint(mid, event);
		                                                    mode = ZOOM;
		                                                    Log.d(TAG, "mode=ZOOM");
		                                                }
		                                                break;

		            case MotionEvent.ACTION_MOVE:

		                                                if (mode == DRAG) 
		                                                { 
		                                                    matrix.set(savedMatrix);
		                                                    matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix  of points
		                                                } 
		                                                else if (mode == ZOOM) 
		                                                { 
		                                                    // pinch zooming
		                                                    float newDist = spacing(event);
		                                                    Log.d(TAG, "newDist=" + newDist);
		                                                    if (newDist > 5f) 
		                                                    {
		                                                        matrix.set(savedMatrix);
		                                                        scale = newDist / oldDist; // setting the scaling of the
		                                                                                    // matrix...if scale > 1 means
		                                                                                    // zoom in...if scale < 1 means
		                                                                                    // zoom out
		                                                        matrix.postScale(scale, scale, mid.x, mid.y);
		                                                    }
		                                                }
		                                                break;
		        }

		        view.setImageMatrix(matrix); // display the transformation on screen

		        return true;
			}
		});
		return convertView;
	}

	public static Bitmap decodeSampledBitmap(String path, int reqWidth, int reqHeight) {

		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

		// Decode bitmap with inSampleSize set
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeFile(path, options);
	}

	public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {
			if (width > height) {
				inSampleSize = Math.round((float) height / (float) reqHeight);
			} else {
				inSampleSize = Math.round((float) width / (float) reqWidth);
			}
		}
		return inSampleSize;
	}
	
	 private float spacing(MotionEvent event) 
	    {
	        float x = event.getX(0) - event.getX(1);
	        float y = event.getY(0) - event.getY(1);
	        return FloatMath.sqrt(x * x + y * y);
	    }
	 
	 private void midPoint(PointF point, MotionEvent event) 
	    {
	        float x = event.getX(0) + event.getX(1);
	        float y = event.getY(0) + event.getY(1);
	        point.set(x / 2, y / 2);
	    }

	    /** Show an event in the LogCat view, for debugging */
	    private void dumpEvent(MotionEvent event) 
	    {
	        String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE","POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
	        StringBuilder sb = new StringBuilder();
	        int action = event.getAction();
	        int actionCode = action & MotionEvent.ACTION_MASK;
	        sb.append("event ACTION_").append(names[actionCode]);

	        if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) 
	        {
	            sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
	            sb.append(")");
	        }

	        sb.append("[");
	        for (int i = 0; i < event.getPointerCount(); i++) 
	        {
	            sb.append("#").append(i);
	            sb.append("(pid ").append(event.getPointerId(i));
	            sb.append(")=").append((int) event.getX(i));
	            sb.append(",").append((int) event.getY(i));
	            if (i + 1 < event.getPointerCount())
	                sb.append(";");
	        }

	        sb.append("]");
	        Log.d("Touch Events ---------", sb.toString());
	    }
}
